package com.kaizeli.website.util;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.Random;

/**
 * 验证码工具类
 * 用于生成4位数字图片验证码
 */
public class CaptchaUtil {

    // 验证码图片宽度
    private static final int WIDTH = 120;
    
    // 验证码图片高度
    private static final int HEIGHT = 40;
    
    // 验证码字符数量
    private static final int CODE_LENGTH = 4;
    
    // 干扰线数量
    private static final int LINE_COUNT = 20;
    
    // 随机数生成器
    private static final Random RANDOM = new Random();
    
    // 验证码字符集（只包含数字0-9）
    private static final char[] CHARS = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
    };

    /**
     * 生成验证码
     * @return CaptchaResult 包含验证码文本和Base64图片
     */
    public static CaptchaResult generateCaptcha() {
        // 生成随机验证码文本
        String code = generateCode();
        
        // 创建图片
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();
        
        // 设置抗锯齿
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        
        // 填充背景色（浅灰色）
        g.setColor(new Color(240, 240, 240));
        g.fillRect(0, 0, WIDTH, HEIGHT);
        
        // 绘制干扰线
        drawInterferenceLines(g);
        
        // 绘制验证码文字
        drawCode(g, code);
        
        // 绘制边框
        g.setColor(new Color(200, 200, 200));
        g.drawRect(0, 0, WIDTH - 1, HEIGHT - 1);
        
        g.dispose();
        
        // 将图片转换为Base64
        String base64Image = imageToBase64(image);
        
        return new CaptchaResult(code, base64Image);
    }

    /**
     * 生成随机验证码文本
     */
    private static String generateCode() {
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < CODE_LENGTH; i++) {
            code.append(CHARS[RANDOM.nextInt(CHARS.length)]);
        }
        return code.toString();
    }

    /**
     * 绘制干扰线
     */
    private static void drawInterferenceLines(Graphics2D g) {
        for (int i = 0; i < LINE_COUNT; i++) {
            int x1 = RANDOM.nextInt(WIDTH);
            int y1 = RANDOM.nextInt(HEIGHT);
            int x2 = RANDOM.nextInt(WIDTH);
            int y2 = RANDOM.nextInt(HEIGHT);
            
            // 使用浅色干扰线
            g.setColor(new Color(
                200 + RANDOM.nextInt(55),
                200 + RANDOM.nextInt(55),
                200 + RANDOM.nextInt(55)
            ));
            g.drawLine(x1, y1, x2, y2);
        }
    }

    /**
     * 绘制验证码文字
     */
    private static void drawCode(Graphics2D g, String code) {
        // 字符间距
        int charWidth = WIDTH / CODE_LENGTH;
        
        for (int i = 0; i < code.length(); i++) {
            // 随机字体大小
            int fontSize = 24 + RANDOM.nextInt(6);
            g.setFont(new Font("Arial", Font.BOLD, fontSize));
            
            // 随机颜色（深色）
            g.setColor(new Color(
                RANDOM.nextInt(100),
                RANDOM.nextInt(100),
                RANDOM.nextInt(100)
            ));
            
            // 随机旋转角度（-15度到15度）
            double angle = (RANDOM.nextDouble() - 0.5) * 0.5;
            
            // 计算字符位置
            int x = i * charWidth + 10;
            int y = HEIGHT / 2 + fontSize / 3;
            
            // 保存原始变换
            var originalTransform = g.getTransform();
            
            // 应用旋转
            g.rotate(angle, x, y);
            
            // 绘制字符
            g.drawString(String.valueOf(code.charAt(i)), x, y);
            
            // 恢复变换
            g.setTransform(originalTransform);
        }
    }

    /**
     * 将BufferedImage转换为Base64字符串
     */
    private static String imageToBase64(BufferedImage image) {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            ImageIO.write(image, "png", baos);
            byte[] imageBytes = baos.toByteArray();
            return "data:image/png;base64," + Base64.getEncoder().encodeToString(imageBytes);
        } catch (IOException e) {
            throw new RuntimeException("验证码图片转换失败", e);
        }
    }

    /**
     * 验证码结果类
     */
    public static class CaptchaResult {
        private final String code;
        private final String image;

        public CaptchaResult(String code, String image) {
            this.code = code;
            this.image = image;
        }

        public String getCode() {
            return code;
        }

        public String getImage() {
            return image;
        }
    }
}

